package avnf_small.delayPercent;

import com.net2plan.interfaces.networkDesign.*;
import com.net2plan.libraries.GraphUtils;

import java.io.File;
import java.util.*;

/**
 * @author shentianyu
 * @date 2020-11-03 14:38
 */

/**
 * 一次运行，三个算法
 */

/**
 * 不同算法阻塞率不同，最后铺设到网络中的请求数也不同
 * 为了更好的对比不同算法资源使用量的情况，采用归一化的方法
 * 将最后的结果除以服务的请求数量,得到归一化值
 */

/**
 * 固定请求数量，改变请求的带宽需求，再进行测试
 */

/**
 * 每次跑完一个算法，还要将所有的请求参数初始化到一开始的状态
 */

/**
 * 当一个请求阻塞，它的延时就设定成延时阈值
 * (thresholdTime-delayTime)/thresholdTime
 */


//判断目前可用的数据中心数量
//如果只有一个数据可用，那么直接选择这个
//如果有多个，再考虑最小值是不是0的情况
//如果最小值不是0，直接复用
//如果最小值是0，先把对应的节点移除，再取次小值，直到取到非0的为止
//如果全为0，那么就选择第一个数据中心
//取到非0值之后，将这个值与某个数相比，如果小于等于这个数，那么直接复用，如果大于，那么去开启一个实例


public class Main {

    static List<NetPlan> requestList = new ArrayList<>();
    static List<NetPlan> requestGroup = new ArrayList<>();

    //存储各项结果，最后打印出来
    static StringBuilder str1 = new StringBuilder();
    static StringBuilder str2 = new StringBuilder();
    static StringBuilder str3 = new StringBuilder();

    //存放已经铺设好的请求集合
    static List<NetPlan> deployedRequestList = new ArrayList<>();

    private static int numberOfAllRequests = 1000;
    private static int numberOfRequests = 10;

    private static double delayFactor = 5.0;

    public static int numberOfKShortestPath = 3;

    public static int numberOfThresholdVNF = 15;
    public static int numberOfThresholdReuse = 2;
    public static int numberOfKLinkMapping = 3;

    public static double BPSKMaxLength = 4000.0;
    public static double QPSKMaxLength = 2000.0;
    public static double QAM_8MaxLength = 1000.0;
    public static double QAM_16MaxLength = 500.0;

    public static int numberOfAllVNFTypes = 3;
    public static int numberOfALLSlots = 15;
    public static int numberOfCPU = 10;
    //改变数据中心的数量
    public static int numberOfDC = 3;

    static List<Double> delaySatisfactionList = new ArrayList<>();
    static List<Integer> servedRequestNumberList = new ArrayList<>();
    static List<Integer> mfsiList = new ArrayList<>();
    static List<Double> averageCostList = new ArrayList<>();
    static List<Integer> totalUsedCPUList = new ArrayList<>();
    static List<Double> totalDelayTimeList = new ArrayList<>();
    static List<Double> blockList = new ArrayList<>();

    public static void main(String[] args) {
        //生成请求
        System.out.println("正在生成请求");
        for(int i = 0; i< numberOfAllRequests; i++){
            NetPlan request = createOneNetPlan();
            requestList.add(request);
        }
        System.out.println("请求生成完毕");

        //先复用算法
        {
            for(int k = 0; k< numberOfAllRequests; k++){
                if(k% numberOfRequests ==0){
                    initialNetPlan();
                    deployedRequestList.clear();
                }
                String ch = "/Users/shentianyu/Desktop/vnf/networkTopologies/6nodes_16links.n2p";
                File f1 = new File(ch);
                NetPlan netPlan = new NetPlan(f1);
                List<Node> subNodes = netPlan.getNodes();
                //System.out.println("start"+(k+1));
                NetPlan request = requestList.get(k);
                requestGroup.add(request);
                List<Link> requestLinks = request.getLinks();
                NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
                LinkMappingReturn linkMappingReturn = new LinkMappingReturn();
                nodeMappingReturn = reuseNodeMapping(netPlan,request);
                if(nodeMappingReturn.isNodeMappingSign()){
                    linkMappingReturn = linkMapping(netPlan,request);
                    if(linkMappingReturn.isLinkMappingSign()){
                        deployedRequestList.add(request);
                        //System.out.println("This request has been successfully served!");
                    } else {
                        //System.out.println("LinkMapping failed!");
                        request.setAttribute("Block","1");
                    }
                } else {
                    //System.out.println("NodeMapping failed!");
                    request.setAttribute("Block","1");
                }

                for(Link link : requestLinks){
                    //System.out.println(link.getAttribute("PathLength"));
                }

                File f_1 = new File(ch);
                netPlan.saveToFile(f_1);

                if(k%numberOfRequests==numberOfRequests-1){
                    for(NetPlan thisRequest:requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            double thresholdTime = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                            double delayTime = thresholdTime*2.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        } else {
                            double delayTime = 0.0;
                            for(Node node:thisRequest.getNodes()){
                                String vnfType = node.getAttribute("VNF");
                                if(!"0".equals(vnfType)){
                                    int subIndex = Integer.valueOf(node.getAttribute("MappedNode")).intValue();
                                    Node subNode = subNodes.get(subIndex);
                                    int numberOfThisVNF = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                                    int vnf = Integer.valueOf(vnfType).intValue();
                                    delayTime += (vnf+1)*delayFactor*numberOfThisVNF;
                                }
                            }
                            double pathLength = 0.0;
                            for(Link link:thisRequest.getLinks()){
                                pathLength += Double.valueOf(link.getAttribute("PathLength")).doubleValue();
                            }
                            delayTime += pathLength/200.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        }
                    }

                    double totalDelayTime = 0.0;
                    double totalThresholdTime = 0.0;
                    int blockNumber = 0;
                    for(NetPlan thisRequest : requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            blockNumber++;
                        }
                        double dt = Double.valueOf(thisRequest.getAttribute("DelayTime")).doubleValue();
                        double tt = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                        totalDelayTime += dt;
                        totalThresholdTime += tt;
                    }

                    double delaySatisfaction = (totalThresholdTime-totalDelayTime)/totalThresholdTime;

                    double block = (blockNumber*1.0)/(numberOfRequests*1.0);
                    netPlan.setAttribute("Block",String.valueOf(block));
                    netPlan.setAttribute("TotalDelayTime",String.valueOf(totalDelayTime));
                    netPlan.setAttribute("TotalThresholdTime",String.valueOf(totalThresholdTime));
                    requestGroup.clear();
                    blockList.add(block);

                    delaySatisfactionList.add(delaySatisfaction);
                    totalDelayTimeList.add(totalDelayTime);
                    servedRequestNumberList.add(numberOfRequests-blockNumber);

                    int mfsi = MFSI(netPlan);
                    netPlan.setAttribute("MFSI",String.valueOf(mfsi));
                    mfsiList.add(mfsi);

                    int totalUsedCPU = 0;
                    for(Node node:subNodes){
                        if("1".equals(node.getAttribute("DataCenter"))){
                            //System.out.println("数据中心"+subNodes.indexOf(node));
                            for(int vnfType =1;vnfType<=numberOfAllVNFTypes;vnfType++){
                                //System.out.print(" VNF"+vnfType+": "+node.getAttribute(String.valueOf(vnfType))+", ");
                                int vnfNum = Integer.valueOf(node.getAttribute(String.valueOf(vnfType))).intValue();
                                if(vnfNum>0){
                                    totalUsedCPU += vnfType;
                                }
                            }
                            //System.out.println();
                        }
                    }
                    totalUsedCPUList.add(totalUsedCPU);
                    netPlan.setAttribute("TotalUsedCPU",String.valueOf(totalUsedCPU));

                    double averageCost = totalDelayTime/totalThresholdTime+((totalUsedCPU*1.0)/(numberOfCPU*numberOfDC*1.0)+(mfsi*1.0)/(numberOfALLSlots*1.0))/(1.0-block);
                    averageCostList.add(averageCost);
                    netPlan.setAttribute("AverageCost",String .valueOf(averageCost));

                    //System.out.println("TotalUsedCpu: "+netPlan.getAttribute("TotalUsedCPU"));
                    //System.out.println("TotalDelayTime: "+netPlan.getAttribute("TotalDelayTime"));
                    //System.out.println("TotalThresholdTime: "+netPlan.getAttribute("TotalThresholdTime"));
                    //System.out.println("MFSI: "+netPlan.getAttribute("MFSI"));
                    //System.out.println("block: "+netPlan.getAttribute("Block"));
                    //System.out.println("AverageCost: "+netPlan.getAttribute("AverageCost"));
                }
                if(k==numberOfAllRequests-1){
                    //System.out.println("-------------------------------------------------");
                    str1.append("-------------------------------------------------"+"\n");

                    //System.out.print("TotalUsedCPU: ");
                    str1.append("TotalUsedCPU: ");
                    for(Integer i:totalUsedCPUList){
                        //System.out.print(i.intValue()+" ");
                        str1.append(i.intValue()+" ");
                    }
                    //System.out.println();
                    str1.append("\n");

                    //System.out.print("MFSI: ");
                    str1.append("MFSI: ");
                    for(Integer i:mfsiList) {
                        //System.out.print(i.intValue()+"  ");
                        str1.append(i.intValue()+"  ");
                    }
                    //System.out.println();
                    str1.append("\n");

                    //System.out.print("TotalDelayTime: ");
                    str1.append("TotalDelayTime: ");
                    for(Double d:totalDelayTimeList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str1.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str1.append("\n");

                    str1.append("NumberOfServedRequests: ");
                    for(Integer i : servedRequestNumberList){
                        str1.append(i.intValue()+" ");
                    }
                    str1.append("\n");

                    //System.out.print("block: ");
                    str1.append("block: ");
                    for(Double d:blockList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str1.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str1.append("\n");
                    //System.out.println();
                    str1.append("\n");

                    //System.out.print("AverageCost: ");
                    str1.append("AverageCost: ");
                    for(Double d:averageCostList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str1.append(String.format("%.6f", d.doubleValue())+"  ");
                    }



                    //System.out.println();
                    str1.append("\n");
                    str1.append("\n");
                    //System.out.println();

                    //System.out.println("My algorithm "+numberOfRequests+" requests");
                    str1.append("My algorithm "+numberOfRequests+" requests"+"\n");

                    //System.out.println("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList));
                    //System.out.println("MFSI avg: "+getAvgValue(mfsiList));
                    //System.out.println("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)));
                    //System.out.println("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList)));
                    //System.out.println("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)));
                    str1.append("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList)+"\n");
                    str1.append("MFSI avg: "+getAvgValue(mfsiList)+"\n");
                    str1.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList))+"\n");
                    str1.append("NumberOfServedRequests avg: "+String.format("%.6f",getAvgValue(servedRequestNumberList))+"\n");
                    str1.append("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList))+"\n");
                    str1.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList))+"\n");
                    str1.append("DelaySatisfaction avg: "+String.format("%.6f",getDoubleAvgValue(delaySatisfactionList))+"\n");
                    str1.append("\n");
                    str1.append("normalization: "+"\n");
                    str1.append("TotalUsedCPU avg: "+String.format("%.6f",getAvgValue(totalUsedCPUList)/getAvgValue(servedRequestNumberList))+"\n");
                    str1.append("MFSI avg: "+String.format("%.6f",getAvgValue(mfsiList)/getAvgValue(servedRequestNumberList))+"\n");
                    str1.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)/getAvgValue(servedRequestNumberList))+"\n");
                    str1.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)/getAvgValue(servedRequestNumberList))+"\n");
                }
            }
        }

        //初始化所有的请求
        initialAllRequests();
        delaySatisfactionList.clear();
        servedRequestNumberList.clear();
        mfsiList.clear();
        averageCostList.clear();
        totalUsedCPUList.clear();
        totalDelayTimeList.clear();
        blockList.clear();

        //SPLB
        {
            for(int k = 0; k< numberOfAllRequests; k++){
                if(k% numberOfRequests ==0){
                    initialNetPlan();
                    deployedRequestList.clear();
                }
                String ch = "/Users/shentianyu/Desktop/vnf/networkTopologies/6nodes_16links.n2p";
                File f1 = new File(ch);
                NetPlan netPlan = new NetPlan(f1);
                List<Node> subNodes = netPlan.getNodes();
                //System.out.println("start"+(k+1));
                NetPlan request = requestList.get(k);
                requestGroup.add(request);
                List<Link> requestLinks = request.getLinks();
                NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
                LinkMappingReturn linkMappingReturn = new LinkMappingReturn();
                nodeMappingReturn = SPLBNodeMapping(netPlan,request);
                if(nodeMappingReturn.isNodeMappingSign()){
                    linkMappingReturn = linkMapping(netPlan,request);
                    if(linkMappingReturn.isLinkMappingSign()){
                        deployedRequestList.add(request);
                        //System.out.println("This request has been successfully served!");
                    } else {
                        //System.out.println("LinkMapping failed!");
                        request.setAttribute("Block","1");
                    }
                } else {
                    //System.out.println("NodeMapping failed!");
                    request.setAttribute("Block","1");
                }

                for(Link link : requestLinks){
                    //System.out.println(link.getAttribute("PathLength"));
                }

                File f_1 = new File(ch);
                netPlan.saveToFile(f_1);

                if(k%numberOfRequests==numberOfRequests-1){
                    for(NetPlan thisRequest:requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            double thresholdTime = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                            double delayTime = thresholdTime*2.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        } else {
                            double delayTime = 0.0;
                            for(Node node:thisRequest.getNodes()){
                                String vnfType = node.getAttribute("VNF");
                                if(!"0".equals(vnfType)){
                                    int subIndex = Integer.valueOf(node.getAttribute("MappedNode")).intValue();
                                    Node subNode = subNodes.get(subIndex);
                                    int numberOfThisVNF = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                                    int vnf = Integer.valueOf(vnfType).intValue();
                                    delayTime += (vnf+1)*delayFactor*numberOfThisVNF;
                                }
                            }
                            double pathLength = 0.0;
                            for(Link link:thisRequest.getLinks()){
                                pathLength += Double.valueOf(link.getAttribute("PathLength")).doubleValue();
                            }
                            delayTime += pathLength/200.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        }
                    }

                    double totalDelayTime = 0.0;
                    double totalThresholdTime = 0.0;
                    int blockNumber = 0;
                    for(NetPlan thisRequest : requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            blockNumber++;
                        }
                        double dt = Double.valueOf(thisRequest.getAttribute("DelayTime")).doubleValue();
                        double tt = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                        totalDelayTime += dt;
                        totalThresholdTime += tt;
                    }

                    double delaySatisfaction = (totalThresholdTime-totalDelayTime)/totalThresholdTime;

                    double block = (blockNumber*1.0)/(numberOfRequests*1.0);
                    netPlan.setAttribute("Block",String.valueOf(block));
                    netPlan.setAttribute("TotalDelayTime",String.valueOf(totalDelayTime));
                    netPlan.setAttribute("TotalThresholdTime",String.valueOf(totalThresholdTime));
                    requestGroup.clear();
                    blockList.add(block);

                    delaySatisfactionList.add(delaySatisfaction);
                    totalDelayTimeList.add(totalDelayTime);
                    servedRequestNumberList.add(numberOfRequests-blockNumber);

                    int mfsi = MFSI(netPlan);
                    netPlan.setAttribute("MFSI",String.valueOf(mfsi));
                    mfsiList.add(mfsi);

                    int totalUsedCPU = 0;
                    for(Node node:subNodes){
                        if("1".equals(node.getAttribute("DataCenter"))){
                            //System.out.println("数据中心"+subNodes.indexOf(node));
                            for(int vnfType =1;vnfType<=numberOfAllVNFTypes;vnfType++){
                                //System.out.print(" VNF"+vnfType+": "+node.getAttribute(String.valueOf(vnfType))+", ");
                                int vnfNum = Integer.valueOf(node.getAttribute(String.valueOf(vnfType))).intValue();
                                if(vnfNum>0){
                                    totalUsedCPU += vnfType;
                                }
                            }
                            //System.out.println();
                        }
                    }
                    totalUsedCPUList.add(totalUsedCPU);
                    netPlan.setAttribute("TotalUsedCPU",String.valueOf(totalUsedCPU));

                    double averageCost = totalDelayTime/totalThresholdTime+((totalUsedCPU*1.0)/(numberOfCPU*numberOfDC*1.0)+(mfsi*1.0)/(numberOfALLSlots*1.0))/(1.0-block);
                    averageCostList.add(averageCost);
                    netPlan.setAttribute("AverageCost",String .valueOf(averageCost));

                    //System.out.println("TotalUsedCpu: "+netPlan.getAttribute("TotalUsedCPU"));
                    //System.out.println("TotalDelayTime: "+netPlan.getAttribute("TotalDelayTime"));
                    //System.out.println("TotalThresholdTime: "+netPlan.getAttribute("TotalThresholdTime"));
                    //System.out.println("MFSI: "+netPlan.getAttribute("MFSI"));
                    //System.out.println("block: "+netPlan.getAttribute("Block"));
                    //System.out.println("AverageCost: "+netPlan.getAttribute("AverageCost"));
                }
                if(k==numberOfAllRequests-1){
                    //System.out.println("-------------------------------------------------");
                    str2.append("-------------------------------------------------"+"\n");

                    //System.out.print("TotalUsedCPU: ");
                    str2.append("TotalUsedCPU: ");
                    for(Integer i:totalUsedCPUList){
                        //System.out.print(i.intValue()+" ");
                        str2.append(i.intValue()+" ");
                    }
                    //System.out.println();
                    str2.append("\n");

                    //System.out.print("MFSI: ");
                    str2.append("MFSI: ");
                    for(Integer i:mfsiList) {
                        //System.out.print(i.intValue()+"  ");
                        str2.append(i.intValue()+"  ");
                    }
                    //System.out.println();
                    str2.append("\n");

                    //System.out.print("TotalDelayTime: ");
                    str2.append("TotalDelayTime: ");
                    for(Double d:totalDelayTimeList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str2.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str2.append("\n");

                    str2.append("NumberOfServedRequests: ");
                    for(Integer i : servedRequestNumberList){
                        str2.append(i.intValue()+" ");
                    }
                    str2.append("\n");

                    //System.out.print("block: ");
                    str2.append("block: ");
                    for(Double d:blockList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str2.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str2.append("\n");
                    //System.out.println();
                    str2.append("\n");

                    //System.out.print("AverageCost: ");
                    str2.append("AverageCost: ");
                    for(Double d:averageCostList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str2.append(String.format("%.6f", d.doubleValue())+"  ");
                    }



                    //System.out.println();
                    str2.append("\n");
                    str2.append("\n");
                    //System.out.println();

                    //System.out.println("My algorithm "+numberOfRequests+" requests");
                    str2.append("SPLB "+numberOfRequests+" requests"+"\n");

                    //System.out.println("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList));
                    //System.out.println("MFSI avg: "+getAvgValue(mfsiList));
                    //System.out.println("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)));
                    //System.out.println("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList)));
                    //System.out.println("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)));
                    str2.append("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList)+"\n");
                    str2.append("MFSI avg: "+getAvgValue(mfsiList)+"\n");
                    str2.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList))+"\n");
                    str2.append("NumberOfServedRequests avg: "+String.format("%.6f",getAvgValue(servedRequestNumberList))+"\n");
                    str2.append("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList))+"\n");
                    str2.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList))+"\n");
                    str2.append("DelaySatisfaction avg: "+String.format("%.6f",getDoubleAvgValue(delaySatisfactionList))+"\n");

                    str2.append("\n");
                    str2.append("normalization: "+"\n");
                    str2.append("TotalUsedCPU avg: "+String.format("%.6f",getAvgValue(totalUsedCPUList)/getAvgValue(servedRequestNumberList))+"\n");
                    str2.append("MFSI avg: "+String.format("%.6f",getAvgValue(mfsiList)/getAvgValue(servedRequestNumberList))+"\n");
                    str2.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)/getAvgValue(servedRequestNumberList))+"\n");
                    str2.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)/getAvgValue(servedRequestNumberList))+"\n");
                }
            }
        }

        //初始化所有的请求
        initialAllRequests();
        delaySatisfactionList.clear();
        servedRequestNumberList.clear();
        mfsiList.clear();
        averageCostList.clear();
        totalUsedCPUList.clear();
        totalDelayTimeList.clear();
        blockList.clear();

        //SPRD
        {
            for(int k = 0; k< numberOfAllRequests; k++){
                if(k% numberOfRequests ==0){
                    initialNetPlan();
                    deployedRequestList.clear();
                }
                String ch = "/Users/shentianyu/Desktop/vnf/networkTopologies/6nodes_16links.n2p";
                File f1 = new File(ch);
                NetPlan netPlan = new NetPlan(f1);
                List<Node> subNodes = netPlan.getNodes();
                //System.out.println("start"+(k+1));
                NetPlan request = requestList.get(k);
                requestGroup.add(request);
                List<Link> requestLinks = request.getLinks();
                NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
                LinkMappingReturn linkMappingReturn = new LinkMappingReturn();
                nodeMappingReturn = SPRDNodeMapping(netPlan,request);
                if(nodeMappingReturn.isNodeMappingSign()){
                    linkMappingReturn = linkMapping(netPlan,request);
                    if(linkMappingReturn.isLinkMappingSign()){
                        deployedRequestList.add(request);
                        //System.out.println("This request has been successfully served!");
                    } else {
                        //System.out.println("LinkMapping failed!");
                        request.setAttribute("Block","1");
                    }
                } else {
                    //System.out.println("NodeMapping failed!");
                    request.setAttribute("Block","1");
                }

                for(Link link : requestLinks){
                    //System.out.println(link.getAttribute("PathLength"));
                }

                File f_1 = new File(ch);
                netPlan.saveToFile(f_1);

                if(k%numberOfRequests==numberOfRequests-1){
                    for(NetPlan thisRequest:requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            double thresholdTime = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                            double delayTime = thresholdTime*2.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        } else {
                            double delayTime = 0.0;
                            for(Node node:thisRequest.getNodes()){
                                String vnfType = node.getAttribute("VNF");
                                if(!"0".equals(vnfType)){
                                    int subIndex = Integer.valueOf(node.getAttribute("MappedNode")).intValue();
                                    Node subNode = subNodes.get(subIndex);
                                    int numberOfThisVNF = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                                    int vnf = Integer.valueOf(vnfType).intValue();
                                    delayTime += (vnf+1)*delayFactor*numberOfThisVNF;
                                }
                            }
                            double pathLength = 0.0;
                            for(Link link:thisRequest.getLinks()){
                                pathLength += Double.valueOf(link.getAttribute("PathLength")).doubleValue();
                            }
                            delayTime += pathLength/200.0;
                            thisRequest.setAttribute("DelayTime",String.valueOf(delayTime));
                        }
                    }

                    double totalDelayTime = 0.0;
                    double totalThresholdTime = 0.0;
                    int blockNumber = 0;
                    for(NetPlan thisRequest : requestGroup){
                        if("1".equals(thisRequest.getAttribute("Block"))){
                            blockNumber++;
                        }
                        double dt = Double.valueOf(thisRequest.getAttribute("DelayTime")).doubleValue();
                        double tt = Double.valueOf(thisRequest.getAttribute("ThresholdTime")).doubleValue();
                        totalDelayTime += dt;
                        totalThresholdTime += tt;
                    }

                    double delaySatisfaction = (totalThresholdTime-totalDelayTime)/totalThresholdTime;

                    double block = (blockNumber*1.0)/(numberOfRequests*1.0);
                    netPlan.setAttribute("Block",String.valueOf(block));
                    netPlan.setAttribute("TotalDelayTime",String.valueOf(totalDelayTime));
                    netPlan.setAttribute("TotalThresholdTime",String.valueOf(totalThresholdTime));
                    requestGroup.clear();
                    blockList.add(block);

                    delaySatisfactionList.add(delaySatisfaction);
                    totalDelayTimeList.add(totalDelayTime);
                    servedRequestNumberList.add(numberOfRequests-blockNumber);

                    int mfsi = MFSI(netPlan);
                    netPlan.setAttribute("MFSI",String.valueOf(mfsi));
                    mfsiList.add(mfsi);

                    int totalUsedCPU = 0;
                    for(Node node:subNodes){
                        if("1".equals(node.getAttribute("DataCenter"))){
                            //System.out.println("数据中心"+subNodes.indexOf(node));
                            for(int vnfType =1;vnfType<=numberOfAllVNFTypes;vnfType++){
                                //System.out.print(" VNF"+vnfType+": "+node.getAttribute(String.valueOf(vnfType))+", ");
                                int vnfNum = Integer.valueOf(node.getAttribute(String.valueOf(vnfType))).intValue();
                                if(vnfNum>0){
                                    totalUsedCPU += vnfType;
                                }
                            }
                            //System.out.println();
                        }
                    }
                    totalUsedCPUList.add(totalUsedCPU);
                    netPlan.setAttribute("TotalUsedCPU",String.valueOf(totalUsedCPU));

                    double averageCost = totalDelayTime/totalThresholdTime+((totalUsedCPU*1.0)/(numberOfCPU*numberOfDC*1.0)+(mfsi*1.0)/(numberOfALLSlots*1.0))/(1.0-block);
                    averageCostList.add(averageCost);
                    netPlan.setAttribute("AverageCost",String .valueOf(averageCost));

                    //System.out.println("TotalUsedCpu: "+netPlan.getAttribute("TotalUsedCPU"));
                    //System.out.println("TotalDelayTime: "+netPlan.getAttribute("TotalDelayTime"));
                    //System.out.println("TotalThresholdTime: "+netPlan.getAttribute("TotalThresholdTime"));
                    //System.out.println("MFSI: "+netPlan.getAttribute("MFSI"));
                    //System.out.println("block: "+netPlan.getAttribute("Block"));
                    //System.out.println("AverageCost: "+netPlan.getAttribute("AverageCost"));
                }
                if(k==numberOfAllRequests-1){
                    //System.out.println("-------------------------------------------------");
                    str3.append("-------------------------------------------------"+"\n");

                    //System.out.print("TotalUsedCPU: ");
                    str3.append("TotalUsedCPU: ");
                    for(Integer i:totalUsedCPUList){
                        //System.out.print(i.intValue()+" ");
                        str3.append(i.intValue()+" ");
                    }
                    //System.out.println();
                    str3.append("\n");

                    //System.out.print("MFSI: ");
                    str3.append("MFSI: ");
                    for(Integer i:mfsiList) {
                        //System.out.print(i.intValue()+"  ");
                        str3.append(i.intValue()+"  ");
                    }
                    //System.out.println();
                    str3.append("\n");

                    //System.out.print("TotalDelayTime: ");
                    str3.append("TotalDelayTime: ");
                    for(Double d:totalDelayTimeList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str3.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str3.append("\n");

                    str3.append("NumberOfServedRequests: ");
                    for(Integer i : servedRequestNumberList){
                        str3.append(i.intValue()+" ");
                    }
                    str3.append("\n");

                    //System.out.print("block: ");
                    str3.append("block: ");
                    for(Double d:blockList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str3.append(String.format("%.6f", d.doubleValue())+"  ");
                    }
                    //System.out.println();
                    str3.append("\n");
                    //System.out.println();
                    str3.append("\n");

                    //System.out.print("AverageCost: ");
                    str3.append("AverageCost: ");
                    for(Double d:averageCostList) {
                        //System.out.print(String.format("%.6f", d.doubleValue())+"  ");
                        str3.append(String.format("%.6f", d.doubleValue())+"  ");
                    }



                    //System.out.println();
                    str3.append("\n");
                    str3.append("\n");
                    //System.out.println();

                    //System.out.println("My algorithm "+numberOfRequests+" requests");
                    str3.append("SPRD "+numberOfRequests+" requests"+"\n");

                    //System.out.println("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList));
                    //System.out.println("MFSI avg: "+getAvgValue(mfsiList));
                    //System.out.println("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)));
                    //System.out.println("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList)));
                    //System.out.println("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)));
                    str3.append("TotalUsedCPU avg: "+getAvgValue(totalUsedCPUList)+"\n");
                    str3.append("MFSI avg: "+getAvgValue(mfsiList)+"\n");
                    str3.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList))+"\n");
                    str3.append("NumberOfServedRequests avg: "+String.format("%.6f",getAvgValue(servedRequestNumberList))+"\n");
                    str3.append("block avg: "+String.format("%.6f",getDoubleAvgValue(blockList))+"\n");
                    str3.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList))+"\n");
                    str3.append("DelaySatisfaction avg: "+String.format("%.6f",getDoubleAvgValue(delaySatisfactionList))+"\n");

                    str3.append("\n");
                    str3.append("normalization: "+"\n");
                    str3.append("TotalUsedCPU avg: "+String.format("%.6f",getAvgValue(totalUsedCPUList)/getAvgValue(servedRequestNumberList))+"\n");
                    str3.append("MFSI avg: "+String.format("%.6f",getAvgValue(mfsiList)/getAvgValue(servedRequestNumberList))+"\n");
                    str3.append("TotalDelayTime avg: "+String.format("%.6f",getDoubleAvgValue(totalDelayTimeList)/getAvgValue(servedRequestNumberList))+"\n");
                    str3.append("AverageCost avg: "+String.format("%.6f",getDoubleAvgValue(averageCostList)/getAvgValue(servedRequestNumberList))+"\n");
                }
            }
        }

        System.out.println(str1.toString());
        System.out.println(str2.toString());
        System.out.println(str3.toString());

    }

    private static void initialAllRequests(){
        for(int i=0;i<numberOfAllRequests;i++){
            initialRequest(requestList.get(i));
        }
    }

    private static void initialRequest(NetPlan request) {
        for(Node node : request.getNodes()){
            node.setAttribute("MappedNode","0");
        }
        for(Link link : request.getLinks()){
            link.setAttribute("PathLength","0");
        }
        request.setAttribute("DelayTime","0");
        request.setAttribute("Block","0");
        int thresholdTime = 0;
        for(Node node:request.getNodes()){
            int vnfType = Integer.valueOf(node.getAttribute("VNF")).intValue();
            if(vnfType!=0){
                thresholdTime += (vnfType+1)*5*numberOfThresholdVNF;
            }
        }
        thresholdTime += 10;
        request.setAttribute("ThresholdTime",String.valueOf(thresholdTime));
    }

    private static NodeMappingReturn reuseNodeMapping(NetPlan netPlan, NetPlan request) {
        NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
        boolean nodeMappingSign = false;
        int sourceNodeIndex,destinationNodeIndex;
        //节点之间的对应关系
        Map<Node,Node> nodePair = new HashMap<>();
        //存放请求中所需的VNF
        List<String> VNFSeq = new ArrayList<>();
        //选择节点的依据
        //Map<Node,Integer> VNFOnDC = new HashMap<>();
        //请求中所有节点的数量
        int numberOfRequestNodes = request.getNumberOfNodes();
        //物理网络中的节点数量
        int numberOfSubNodes = netPlan.getNumberOfNodes();
        //物理网络中的所有节点
        List<Node> subNodeList = netPlan.getNodes();
        //请求中的link集合
        List<Link> requestLinkList = request.getLinks();

        for(int i=1;i<numberOfRequestNodes-1;i++){
            VNFSeq.add(request.getNode(i).getAttribute("VNF"));
        }
        //System.out.print("所需的VNF ");
        for(String s : VNFSeq){
            //System.out.print(s+" ");
        }
        //System.out.println();

        //分配源节点和目的节点
        Node sourceNode = request.getNode(0);
        Node destinationNode = request.getNode(numberOfRequestNodes-1);
        sourceNodeIndex = (int)(Math.random()*numberOfSubNodes);
        //System.out.println("源节点 "+sourceNodeIndex);
        while(true){
            destinationNodeIndex = (int)(Math.random()*numberOfSubNodes);
            if(destinationNodeIndex!=sourceNodeIndex){
                break;
            }
        }
        //System.out.println("目的节点 "+destinationNodeIndex);

        nodePair.put(sourceNode,netPlan.getNode(sourceNodeIndex));
        nodePair.put(destinationNode,netPlan.getNode(destinationNodeIndex));
        sourceNode.setAttribute("MappedNode",String.valueOf(sourceNodeIndex));
        destinationNode.setAttribute("MappedNode",String.valueOf(destinationNodeIndex));

        //获取源目的节点之间的多条最短路径
        Map<Link,Double> linkCostMap = new HashMap<>();
        for(Link link:netPlan.getLinks()){
            linkCostMap.put(link,link.getLengthInKm());
        }

        List<List<Link>> kShortestPathList = GraphUtils.getKLooplessShortestPaths(netPlan.getNodes(),netPlan.getLinks(),netPlan.getNode(sourceNodeIndex),netPlan.getNode(destinationNodeIndex),linkCostMap,numberOfKShortestPath,Double.MAX_VALUE, Integer.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE);

        /**
         * 最大的循环是对最短路径进行遍历，从最短路径开始，
         * 如果路径上有数据中心，并且铺设完之后不对之前铺设完的请求产生影响，那么直接结束
         * 第二层循环是对请求中的vnf序列进行，先得到可用的数据中心集合，尽可能复用已有的vnf，并且是复用目前次数最少的那个
         * 理想情况是这样的，先试一下开启新的实例结果怎么样
         * 如果都没有，那么在第一个数据中心上开辟一个新的实例。
         * 在获取可用数据中心集合时，要注意不能有回路，所以要先看前一个节点铺设的位置
         */

        labelA:
        for(int k=0;k<numberOfKShortestPath;k++){
            List<Link> candidatePath = kShortestPathList.get(k);
            //存放当前链路上的所有节点
            List<Node> pathNodes = new ArrayList<>();
            pathNodes.add(candidatePath.get(0).getOriginNode());
            for(Link link:candidatePath) {
                pathNodes.add(link.getDestinationNode());
            }
            //存放节点序号
            List<Integer> pathNodeNo = new ArrayList<>();
            for(Node node:pathNodes){
                pathNodeNo.add(subNodeList.indexOf(node));
            }

            for(int r=1;r<numberOfRequestNodes-1;r++){
                Node formerNode = request.getNode(r-1);
                Node tempNode = request.getNode(r);
                String vnfType = tempNode.getAttribute("VNF");
                //获取前一个点的铺设位置
                int formerNo = Integer.valueOf(formerNode.getAttribute("MappedNode")).intValue();
                int index = pathNodeNo.indexOf(formerNo);
                List<Node> DCNodes = new ArrayList<>();
                for(int i = index;i<pathNodes.size();i++){
                   if("1".equals(pathNodes.get(i).getAttribute("DataCenter"))){
                        DCNodes.add(pathNodes.get(i));
                   }
                }
                //如果当前的请求节点没有数据中心可用，那么考虑下一条路径，并且前面的节点也都要重新选择新的铺设点
                if(DCNodes.isEmpty()){
                    //把前面的vnf节点占用的资源释放
                    for(int i=r-1;i>=1;i--){
                        Node releaseNode = request.getNode(i);
                        //对应铺设上去的DC节点
                        int subIndex = Integer.valueOf(releaseNode.getAttribute("MappedNode")).intValue();
                        Node subNode = subNodeList.get(subIndex);
                        //将铺设上去的请求去掉
                        int before = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                        before--;
                        if(before==0){
                            StringBuilder stringBuilder = new StringBuilder();
                            stringBuilder.append(subNode.getAttribute("VNF"));
                            stringBuilder.deleteCharAt(stringBuilder.length()-1);
                            subNode.setAttribute("VNF",stringBuilder.toString());
                        }
                        subNode.setAttribute(vnfType,String.valueOf(before));
                        releaseNode.setAttribute("MappedNode","0");
                        nodePair.remove(releaseNode);
                    }
                    //考虑下一条路径
                    continue labelA;
                }

                //因为想尽量分散，所以如果可用的数据中心数量大于1，直接不考虑第一个
                //如果阻塞率上升，可以考虑把这句代码去掉(增加可选数据中心的数量)
//                if(DCNodes.size()>1){
//                    DCNodes.remove(0);
//                }

                //根据对当前vnf的复用度进行排序，优先选择复用度最小的数据中心，如果是0，那么直接开启新的实例
                List<Integer> VNFOnDC = new ArrayList<>();
                List<Integer> copyIndex = new ArrayList<>();
                for(Node DCNode :DCNodes){
                    VNFOnDC.add(Integer.valueOf(DCNode.getAttribute(vnfType)));
                    copyIndex.add(Integer.valueOf(DCNode.getAttribute(vnfType)));
                }

                Integer min = Collections.min(VNFOnDC);
                int num = copyIndex.indexOf(min);

                //判断目前可用的数据中心数量
                //如果只有一个数据可用，那么直接选择这个
                //如果有多个，再考虑最小值是不是0的情况
                //如果最小值不是0，直接复用
                //如果最小值是0，先把对应的节点移除，再取次小值，直到取到非0的为止
                //如果全为0，那么就选择第一个数据中心
                //取到非0值之后，将这个值与某个数相比，如果小于等于这个数，那么直接复用，如果大于，那么去开启一个实例

                while(VNFOnDC.size()>1&&min==0){
                    //这个方法走的是移除对应序号的重载方法
                    VNFOnDC.remove(min);
                    min = Collections.min(VNFOnDC);
                    //小于阈值时，允许复用
                    if(min!=0&&min<=numberOfThresholdReuse){
                        num = copyIndex.indexOf(min);
                    }
                }

                Node selectedDC = DCNodes.get(num);
                //VNFOnDC.remove(selectedDC);
                int before = Integer.valueOf(selectedDC.getAttribute(vnfType));

                if(before==0){
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(selectedDC.getAttribute("VNF"));
                    stringBuilder.append(vnfType);
                    selectedDC.setAttribute("VNF",stringBuilder.toString());
                }
                before++;
                selectedDC.setAttribute(vnfType,String.valueOf(before));
                tempNode.setAttribute("MappedNode",String.valueOf(subNodeList.indexOf(selectedDC)));
                nodePair.put(tempNode,selectedDC);
            }

            //判断当前请求内的所有节点是否都已经铺设好了
            if(nodePair.size()==numberOfRequestNodes){
                //请求中所有点铺设好之后，判断自己会否满足延时要求并且是否对之前已经铺设在网络中的请求产生了影响
                boolean isOK = verify(netPlan,request)&&verify(netPlan,deployedRequestList);
                if(!isOK){
                    //如果有影响，那么要释放掉所有的资源，重新考虑新的路径
                    for(int i=numberOfRequestNodes-2;i>0;i--){
                        Node releaseNode = request.getNode(i);
                        String vnfType = releaseNode.getAttribute("VNF");
                        //对应铺设上去的DC节点
                        int subIndex = Integer.valueOf(releaseNode.getAttribute("MappedNode")).intValue();
                        Node subNode = subNodeList.get(subIndex);
                        //将铺设上去的请求去掉
                        int before = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                        before--;
                        if(before==0){
                            StringBuilder stringBuilder = new StringBuilder();
                            stringBuilder.append(subNode.getAttribute("VNF"));
                            stringBuilder.deleteCharAt(stringBuilder.length()-1);
                            subNode.setAttribute("VNF",stringBuilder.toString());
                        }
                        subNode.setAttribute(vnfType,String.valueOf(before));
                        releaseNode.setAttribute("MappedNode","0");
                        nodePair.remove(releaseNode);
                    }
                    continue labelA;
                }else{
                    //如果没有，那么直接跳过,本次请求结束
                    nodeMappingSign = true;
                    break labelA;
                }
            }
        }

        if(nodeMappingSign){
            //节点映射成功
            //System.out.println("节点映射成功");
            for(Link link:requestLinkList){
                int origin = subNodeList.indexOf(nodePair.get(link.getOriginNode()));
                int destination = subNodeList.indexOf(nodePair.get(link.getDestinationNode()));
                if(origin!=destination){
                    netPlan.addDemand(nodePair.get(link.getOriginNode()),nodePair.get(link.getDestinationNode()),link.getCapacity(),null,netPlan.getNetworkLayerDefault());
                }
            }
        }else{
            //节点映射失败
            request.setAttribute("Block","1");
            int blockedRequests = Integer.valueOf(netPlan.getAttribute("BlockedRequest")).intValue();
            blockedRequests++;
            netPlan.setAttribute("BlockedRequest",String.valueOf(blockedRequests));
            //System.out.println("节点映射失败");
        }
        nodeMappingReturn.setNodeMappingSign(nodeMappingSign);
        return nodeMappingReturn;
    }

    private static NodeMappingReturn SPRDNodeMapping(NetPlan netPlan, NetPlan request) {
        NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
        boolean nodeMappingSign = false;
        int sourceNodeIndex,destinationNodeIndex;
        //节点之间的对应关系
        Map<Node,Node> nodePair = new HashMap<>();
        //存放请求中所需的VNF
        List<String> VNFSeq = new ArrayList<>();
        //选择节点的依据
        Map<Node,Integer> VNFOnDC = new HashMap<>();
        //请求中所有节点的数量
        int numberOfRequestNodes = request.getNumberOfNodes();
        //物理网络中的节点数量
        int numberOfSubNodes = netPlan.getNumberOfNodes();
        //物理网络中的所有节点
        List<Node> subNodeList = netPlan.getNodes();
        //请求中的link集合
        List<Link> requestLinkList = request.getLinks();


        for(int i=1;i<numberOfRequestNodes-1;i++){
            VNFSeq.add(request.getNode(i).getAttribute("VNF"));
        }
        //System.out.print("所需的VNF ");
        for(String s : VNFSeq){
            System.out.print(s+" ");
        }
        //System.out.println();

        //分配源节点和目的节点
        Node sourceNode = request.getNode(0);
        Node destinationNode = request.getNode(numberOfRequestNodes-1);
        sourceNodeIndex = (int)(Math.random()*numberOfSubNodes);
        //System.out.println("源节点 "+sourceNodeIndex);
        while(true){
            destinationNodeIndex = (int)(Math.random()*numberOfSubNodes);
            if(destinationNodeIndex!=sourceNodeIndex){
                break;
            }
        }
        //System.out.println("目的节点 "+destinationNodeIndex);

        nodePair.put(sourceNode,netPlan.getNode(sourceNodeIndex));
        nodePair.put(destinationNode,netPlan.getNode(destinationNodeIndex));
        sourceNode.setAttribute("MappedNode",String.valueOf(sourceNodeIndex));
        destinationNode.setAttribute("MappedNode",String.valueOf(destinationNodeIndex));

        //获取源目的节点之间的多条最短路径
        Map<Link,Double> linkCostMap = new HashMap<>();
        for(Link link:netPlan.getLinks()){
            linkCostMap.put(link,link.getLengthInKm());
        }

        List<List<Link>> kShortestPathList = GraphUtils.getKLooplessShortestPaths(netPlan.getNodes(),netPlan.getLinks(),netPlan.getNode(sourceNodeIndex),netPlan.getNode(destinationNodeIndex),linkCostMap,numberOfKShortestPath,Double.MAX_VALUE, Integer.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE);

        /**
         * 从最短路径开始遍历，只要有数据中心即可
         * 如果三条最短路径都没数据中心，那么直接阻塞
         * 对每个vnf节点进行铺设，先得到当前节点的可用数据中心节点集合
         */
        List<Node> DCNodeOnPath = new ArrayList<>();
        for(int i = 0;i<numberOfKShortestPath;i++){
            List<Link> shortestPath = kShortestPathList.get(i);
            //.............
            //code here
            Node originNode = shortestPath.get(0).getOriginNode();
            if("1".equals(originNode.getAttribute("DataCenter"))){
                DCNodeOnPath.add(originNode);
            }
            for(int j =0;j<shortestPath.size();j++){
                Node node = shortestPath.get(j).getDestinationNode();
                if("1".equals(node.getAttribute("DataCenter"))){
                    DCNodeOnPath.add(node);
                }
            }
            //如果最短路径上有数据中心，直接进行后续操作
            if(DCNodeOnPath.size()>0){
                break;
            }
        }

        if(DCNodeOnPath.isEmpty()){
            nodeMappingSign = false;
            nodeMappingReturn.setNodeMappingSign(nodeMappingSign);
            return nodeMappingReturn;
        }

        //对请求中的vnf节点分别进行处理
        //先得到可用的数据中心节点集合（根据前一个节点的铺设位置）
        //然后随机选一个进行铺设

        for(int i=1;i<numberOfRequestNodes-1;i++){
            //备选数据中心集合
            List<Node> candidateDC = new ArrayList<>();
            Node vnfNode = request.getNode(i);
            Node preNode = request.getNode(i-1);
            if(i==1){
                for(int j=0;j<DCNodeOnPath.size();j++){
                    candidateDC.add(DCNodeOnPath.get(j));
                }
            } else {
                int subIndex = Integer.valueOf(preNode.getAttribute("MappedNode")).intValue();
                Node preDC = subNodeList.get(subIndex);
                int index = DCNodeOnPath.indexOf(preDC);
                for(int j = index;j<DCNodeOnPath.size();j++){
                    candidateDC.add(DCNodeOnPath.get(j));
                }
            }

            int ran = (int)(Math.random()*candidateDC.size());
            Node selectedDC = candidateDC.get(ran);

            String vnfType = vnfNode.getAttribute("VNF");
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(selectedDC.getAttribute("VNF"));
            int before = Integer.valueOf(selectedDC.getAttribute(vnfType)).intValue();
            if(before==0){
                stringBuilder.append(vnfType);
            }
            before++;
            selectedDC.setAttribute(vnfType,String.valueOf(before));
            selectedDC.setAttribute("VNF",stringBuilder.toString());
            vnfNode.setAttribute("MappedNode",String.valueOf(subNodeList.indexOf(selectedDC)));
            nodePair.put(vnfNode,selectedDC);
        }


        //选中的数据中心，将当前请求的所有VNF都放到一个数据中心上
        //放完之后，判断自己是否符合延时要求，是否对已经铺设好的请求产生了影响
        boolean isOk = verify(netPlan,request)&&verify(netPlan,deployedRequestList);

        if(isOk){
            //当前铺设方案可行
            nodeMappingSign = true;
        } else {
            //将铺设上去的请求去掉
            for(int i=numberOfRequestNodes-2;i>=1;i--){
                Node releaseNode = request.getNode(i);
                int dcNum = Integer.valueOf(releaseNode.getAttribute("MappedNode")).intValue();
                Node selectedDC = subNodeList.get(dcNum);
                StringBuilder str = new StringBuilder();
                str.append(selectedDC.getAttribute("VNF"));
                String vnfType = releaseNode.getAttribute("VNF");
                int before = Integer.valueOf(selectedDC.getAttribute(vnfType)).intValue();
                if(before == 1){
                    str.deleteCharAt(str.length()-1);
                }
                before--;
                selectedDC.setAttribute("VNF",str.toString());
                selectedDC.setAttribute(vnfType,String.valueOf(before));
                releaseNode.setAttribute("MappedNode","0");
                nodePair.remove(releaseNode);
            }
            nodeMappingSign = false;
        }

        if(nodeMappingSign){
            //节点映射成功
            //System.out.println("节点映射成功");
            for(Link link:requestLinkList){
                int origin = subNodeList.indexOf(nodePair.get(link.getOriginNode()));
                int destination = subNodeList.indexOf(nodePair.get(link.getDestinationNode()));
                if(origin!=destination){
                    netPlan.addDemand(nodePair.get(link.getOriginNode()),nodePair.get(link.getDestinationNode()),link.getCapacity(),null,netPlan.getNetworkLayerDefault());
                }
            }
        }else{
            //节点映射失败
            request.setAttribute("Block","1");
            int blockedRequests = Integer.valueOf(netPlan.getAttribute("BlockedRequest")).intValue();
            blockedRequests++;
            netPlan.setAttribute("BlockedRequest",String.valueOf(blockedRequests));
            //System.out.println("节点映射失败");
        }
        nodeMappingReturn.setNodeMappingSign(nodeMappingSign);
        return nodeMappingReturn;
    }

    private static NodeMappingReturn SPLBNodeMapping(NetPlan netPlan, NetPlan request) {
        NodeMappingReturn nodeMappingReturn = new NodeMappingReturn();
        boolean nodeMappingSign = false;
        int sourceNodeIndex,destinationNodeIndex;
        //节点之间的对应关系
        Map<Node,Node> nodePair = new HashMap<>();
        //存放请求中所需的VNF
        List<String> VNFSeq = new ArrayList<>();
        //选择节点的依据
        Map<Node,Integer> VNFOnDC = new HashMap<>();
        //请求中所有节点的数量
        int numberOfRequestNodes = request.getNumberOfNodes();
        //物理网络中的节点数量
        int numberOfSubNodes = netPlan.getNumberOfNodes();
        //物理网络中的所有节点
        List<Node> subNodeList = netPlan.getNodes();
        //请求中的link集合
        List<Link> requestLinkList = request.getLinks();


        for(int i=1;i<numberOfRequestNodes-1;i++){
            VNFSeq.add(request.getNode(i).getAttribute("VNF"));
        }
        //System.out.print("所需的VNF ");
        for(String s : VNFSeq){
            //System.out.print(s+" ");
        }
        //System.out.println();

        //分配源节点和目的节点
        Node sourceNode = request.getNode(0);
        Node destinationNode = request.getNode(numberOfRequestNodes-1);
        sourceNodeIndex = (int)(Math.random()*numberOfSubNodes);
        //System.out.println("源节点 "+sourceNodeIndex);
        while(true){
            destinationNodeIndex = (int)(Math.random()*numberOfSubNodes);
            if(destinationNodeIndex!=sourceNodeIndex){
                break;
            }
        }
        //System.out.println("目的节点 "+destinationNodeIndex);

        nodePair.put(sourceNode,netPlan.getNode(sourceNodeIndex));
        nodePair.put(destinationNode,netPlan.getNode(destinationNodeIndex));
        sourceNode.setAttribute("MappedNode",String.valueOf(sourceNodeIndex));
        destinationNode.setAttribute("MappedNode",String.valueOf(destinationNodeIndex));

        //获取源目的节点之间的多条最短路径
        Map<Link,Double> linkCostMap = new HashMap<>();
        for(Link link:netPlan.getLinks()){
            linkCostMap.put(link,link.getLengthInKm());
        }

        List<List<Link>> kShortestPathList = GraphUtils.getKLooplessShortestPaths(netPlan.getNodes(),netPlan.getLinks(),netPlan.getNode(sourceNodeIndex),netPlan.getNode(destinationNodeIndex),linkCostMap,numberOfKShortestPath,Double.MAX_VALUE, Integer.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE);

        /**
         * 从最短路径开始遍历，只要有数据中心即可
         * 如果三条最短路径都没数据中心，那么直接阻塞
         * 数据中心的属性 Load， 有一个复用就加1
         */
        List<Node> DCNodeOnPath = new ArrayList<>();
        for(int i = 0;i<numberOfKShortestPath;i++){
            List<Link> shortestPath = kShortestPathList.get(i);
            //.............
            //code here
            Node originNode = shortestPath.get(0).getOriginNode();
            if("1".equals(originNode.getAttribute("DataCenter"))){
                DCNodeOnPath.add(originNode);
            }
            for(int j =0;j<shortestPath.size();j++){
                Node node = shortestPath.get(j).getDestinationNode();
                if("1".equals(node.getAttribute("DataCenter"))){
                    DCNodeOnPath.add(node);
                }
            }
            //如果最短路径上有数据中心，直接进行后续操作
            if(DCNodeOnPath.size()>0){
                for(Node node:DCNodeOnPath){
                    Integer load = Integer.valueOf(node.getAttribute("Load"));
                    VNFOnDC.put(node,load);
                }
                break;
            }
        }

        if(DCNodeOnPath.isEmpty()||VNFOnDC.isEmpty()){
            nodeMappingSign = false;
            nodeMappingReturn.setNodeMappingSign(nodeMappingSign);
            return nodeMappingReturn;
        }

        int min = Collections.min(VNFOnDC.values());
        Node selectedDC = null;
        for(Map.Entry<Node,Integer> it :VNFOnDC.entrySet()){
            if(it.getValue()==min){
                selectedDC = it.getKey();
                break;
            }
        }

        //选中的数据中心，将当前请求的所有VNF都放到一个数据中心上
        //放完之后，判断自己是否符合延时要求，是否对已经铺设好的请求产生了影响
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(selectedDC.getAttribute("VNF"));
        int load = Integer.valueOf(selectedDC.getAttribute("Load")).intValue();
        for(String vnfType: VNFSeq){
            int before = Integer.valueOf(selectedDC.getAttribute(vnfType)).intValue();
            if(before==0){
                stringBuilder.append(vnfType);
            }
            before++;
            selectedDC.setAttribute(vnfType,String.valueOf(before));
            load++;
        }
        selectedDC.setAttribute("VNF",stringBuilder.toString());
        selectedDC.setAttribute("Load",String.valueOf(load));
        for(int i=1;i<numberOfRequestNodes-1;i++){
            nodePair.put(request.getNode(i),selectedDC);
            request.getNode(i).setAttribute("MappedNode",String.valueOf(subNodeList.indexOf(selectedDC)));
        }

        boolean isOk = verify(netPlan,request)&&verify(netPlan,deployedRequestList);

        if(isOk){
            //当前铺设方案可行
            nodeMappingSign = true;
        } else {
            //将铺设上去的请求去掉
            StringBuilder str = new StringBuilder();
            str.append(selectedDC.getAttribute("VNF"));
            int curLoad = Integer.valueOf(selectedDC.getAttribute("Load")).intValue();
            for(String vnfType:VNFSeq){
                int before = Integer.valueOf(selectedDC.getAttribute(vnfType)).intValue();
                before--;
                if(before==0){
                    str.deleteCharAt(str.length()-1);
                }
                selectedDC.setAttribute(vnfType,String.valueOf(before));
                curLoad--;
            }
            selectedDC.setAttribute("VNF",str.toString());
            selectedDC.setAttribute("Load",String.valueOf(curLoad));
            nodeMappingSign = false;
        }

        if(nodeMappingSign){
            //节点映射成功
            //System.out.println("节点映射成功");
            for(Link link:requestLinkList){
                int origin = subNodeList.indexOf(nodePair.get(link.getOriginNode()));
                int destination = subNodeList.indexOf(nodePair.get(link.getDestinationNode()));
                if(origin!=destination){
                    netPlan.addDemand(nodePair.get(link.getOriginNode()),nodePair.get(link.getDestinationNode()),link.getCapacity(),null,netPlan.getNetworkLayerDefault());
                }
            }
        }else{
            //节点映射失败
            request.setAttribute("Block","1");
            int blockedRequests = Integer.valueOf(netPlan.getAttribute("BlockedRequest")).intValue();
            blockedRequests++;
            netPlan.setAttribute("BlockedRequest",String.valueOf(blockedRequests));
            //System.out.println("节点映射失败");
        }
        nodeMappingReturn.setNodeMappingSign(nodeMappingSign);
        return nodeMappingReturn;
    }

    private static boolean verify(NetPlan netPlan,NetPlan request){
        double delayTime = calculateDelayTime(netPlan, request);
        double thresholdTime = Double.valueOf(request.getAttribute("ThresholdTime")).doubleValue();
        if(delayTime>thresholdTime){
            return false;
        }
        return true;
    }

    private static boolean verify(NetPlan netPlan,List<NetPlan> deployedRequestList) {
        boolean res = true;
        for(NetPlan request:deployedRequestList){
            double delayTime = calculateDelayTime(netPlan,request);
            double thresholdTime = Double.valueOf(request.getAttribute("ThresholdTime")).doubleValue();
            if(delayTime>thresholdTime){
                res = false;
                break;
            }
        }
        return res;
    }

    private static double calculateDelayTime(NetPlan netPlan, NetPlan request) {
        double delayTime = 0.0;
        List<Node> subNodes = netPlan.getNodes();
        for(Node node:request.getNodes()){
            String vnfType = node.getAttribute("VNF");
            if(!"0".equals(vnfType)){
                int subIndex = Integer.valueOf(node.getAttribute("MappedNode")).intValue();
                Node subNode = subNodes.get(subIndex);
                int numberOfThisVNF = Integer.valueOf(subNode.getAttribute(vnfType)).intValue();
                int vnf = Integer.valueOf(vnfType).intValue();
                delayTime += (vnf+1)*delayFactor*numberOfThisVNF;
            }
        }
        double pathLength = 0.0;
        for(Link link:request.getLinks()){
            pathLength += Double.valueOf(link.getAttribute("PathLength")).doubleValue();
        }
        delayTime+=pathLength/200.0;
        return delayTime;
    }

    private static LinkMappingReturn linkMapping(NetPlan netPlan, NetPlan request) {
        LinkMappingReturn linkMappingReturn = new LinkMappingReturn();
        List<Node> subNodes = netPlan.getNodes();
        List<Link> requestLinks = request.getLinks();
        boolean linkMappingSign = true;
        //System.out.println("demand "+netPlan.getNumberOfDemands());
        List<Demand> demandList = netPlan.getDemands();
        for(Demand demand:demandList){
            double capacity = demand.getOfferedTraffic();
            //System.out.println(capacity);
            Node startNode = demand.getIngressNode();
            Node endNode = demand.getEgressNode();
            Map<Link,Double> linkCostMap = new HashMap<>();
            for(Link link:netPlan.getLinks()){
                linkCostMap.put(link,link.getLengthInKm());
            }
            List<List<Link>> kShortestPathList = GraphUtils.getKLooplessShortestPaths(netPlan.getNodes(),netPlan.getLinks(),startNode,endNode,linkCostMap,numberOfKLinkMapping,Double.MAX_VALUE,Integer.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE,Double.MAX_VALUE);
            List<List<Link>> candidatePathList = new ArrayList<>();
            for(int i=0;i<numberOfKLinkMapping;i++){
                List<Link> tempPath = kShortestPathList.get(i);
                Double pathLength = 0.0;
                for(Link link:tempPath){
                    pathLength += link.getLengthInKm();
                }
                if(pathLength<=BPSKMaxLength){
                    candidatePathList.add(tempPath);
                }
            }
            if(candidatePathList.isEmpty()){
                removeAllLayerDemand(netPlan);
                linkMappingSign = false;
                linkMappingReturn.setLinkMappingSign(linkMappingSign);
                return linkMappingReturn;
            }
            List<Integer> mfsiList = new ArrayList<>();
            List<Link> selectedPath = new ArrayList<>();
            for(int i=0;i<candidatePathList.size();i++){
                List<Link> candidatePath = candidatePathList.get(i);
                double pathLength = 0.0;
                for(Link link:candidatePath){
                    pathLength += link.getLengthInKm();
                }
                double modLevel = 0.0;
                int key = (int)(Math.floor(pathLength/QAM_16MaxLength));
                switch(key){
                    case 1: modLevel = 4.0;break;
                    case 2: modLevel = 3.0;break;
                    case 3: modLevel = 2.0;break;
                    case 4: modLevel = 2.0;break;
                    default: modLevel = 1.0;break;
                }
                int numberOfSlotNeeded = (int)Math.ceil(capacity/(12.5*modLevel));
                int[] pathStatus = new int[numberOfALLSlots];
                for(Link link : candidatePath){
                    String linkStatus = link.getAttribute("LinkStatus");
                    int[] s1 = stringToIntArray(linkStatus);
                    for(int m=0;m<numberOfALLSlots;m++){
                        if(pathStatus[m]==0&&s1[m]==0){
                            pathStatus[m] = 0;
                        } else {
                            pathStatus[m] = 1;
                        }
                    }
                }
                int startIndex = 0;
                int endIndex = 0;
                int flag = 0;
                int count = 0;
                for(int m=0;m<numberOfALLSlots;m++){
                    count++;
                    if(pathStatus[m]==0){
                        flag++;
                    } else {
                        flag = 0;
                    }
                    if(flag==numberOfSlotNeeded){
                        endIndex = m;
                        startIndex = endIndex-numberOfSlotNeeded+1;
                        break;
                    }
                }
                if(count==numberOfALLSlots&&endIndex==0){
                    mfsiList.add(numberOfALLSlots+1);
                    continue;
                }
                for(int m=startIndex;m<=endIndex;m++){
                    pathStatus[m] = 1;
                }
                int mfsi = 0;
                for(int m=0;m<numberOfALLSlots;m++){
                    if(pathStatus[m]==1){
                        mfsi = m+1;
                    }
                }
                mfsiList.add(mfsi);
            }
            int kMin = Collections.min(mfsiList);
            if(kMin==numberOfALLSlots+1){
                removeAllLayerDemand(netPlan);
                linkMappingSign = false;
                linkMappingReturn.setLinkMappingSign(linkMappingSign);
                return linkMappingReturn;
            }
            int kIndex = mfsiList.indexOf(kMin);
            selectedPath = candidatePathList.get(kIndex);

            int[] pathStatusBefore = new int[numberOfALLSlots];
            double pathLength = 0.0;
            for(Link link:selectedPath){
                pathLength+=link.getLengthInKm();
            }
            String startNodeIndex = String.valueOf(subNodes.indexOf(startNode));
            String endNodeIndex = String.valueOf(subNodes.indexOf(endNode));
            for(Link link:requestLinks){
                if(link.getOriginNode().getAttribute("MappedNode").equals(startNodeIndex)&&link.getDestinationNode().getAttribute("MappedNode").equals(endNodeIndex)){
                    link.setAttribute("PathLength",String.valueOf(pathLength));
                    break;
                }
            }
            double modLevel = 0.0;
            int key = (int)(Math.floor(pathLength/QAM_16MaxLength));
            switch(key){
                case 1: modLevel = 4.0; break;
                case 2: modLevel = 3.0; break;
                case 3: modLevel = 2.0; break;
                case 4: modLevel = 2.0; break;
                default: modLevel = 1.0; break;
            }
            int numberOfSlotNeeded = (int)Math.ceil(capacity/(12.5*modLevel));
            for(Link link:selectedPath){
                String s = link.getAttribute("LinkStatus");
                int[] s1 = stringToIntArray(s);
                for(int m=0;m<numberOfALLSlots;m++){
                    if(pathStatusBefore[m]==0&&s1[m]==0){
                        pathStatusBefore[m]=0;
                    } else {
                        pathStatusBefore[m] = 1;
                    }
                }
            }
            int startIndex = 0;
            int endIndex = 0;
            int flag = 0;
            for(int m=0;m<numberOfALLSlots;m++){
                if(pathStatusBefore[m]==0){
                    flag++;
                } else {
                    flag = 0;
                }
                if(flag==numberOfSlotNeeded){
                    endIndex = m;
                    startIndex = endIndex-numberOfSlotNeeded+1;
                    break;
                }
            }
            for(Link link:selectedPath){
                String s = link.getAttribute("LinkStatus");
                int[] s1 = stringToIntArray(s);
                for(int i = startIndex;i<=endIndex;i++){
                    s1[i] = 1;
                }
                s = intArrayToString(s1);
                link.setAttribute("LinkStatus",s);
            }
        }
        removeAllLayerDemand(netPlan);
        linkMappingReturn.setLinkMappingSign(linkMappingSign);
        return linkMappingReturn;
    }

    private static String intArrayToString(int[] arr) {
        StringBuilder stringBuilder = new StringBuilder();
        for(int i:arr){
            stringBuilder.append(i);
        }
        return stringBuilder.toString();
    }

    private static double getAvgValue(List<Integer> list){
        double avgValue;
        double sum = 0.0;
        int num = list.size();
        for(int i:list){
            sum = (double)i+sum;
        }
        avgValue = sum/(num*1.0);
        return avgValue;
    }

    private static double getDoubleAvgValue(List<Double> list){
        double avgValue;
        double sum = 0.0;
        int num = list.size();
        for(double i:list){
            sum = i+sum;
        }
        avgValue = sum/(num*1.0);
        return avgValue;
    }

    private static int MFSI(NetPlan netPlan) {
        int mfsiIndex;
        List<Link> linkList = netPlan.getLinks();
        List<Integer> maxIndexList = new ArrayList<>();
        for(Link link:linkList){
            String s = link.getAttribute("LinkStatus");
            int[] s1 = stringToIntArray(s);
            int max = 0;
            for(int i=0;i<numberOfALLSlots;i++){
                if(s1[i]==1){
                    max = i;
                }
            }
            maxIndexList.add(max);
        }
        mfsiIndex = Collections.max(maxIndexList);
        return mfsiIndex+1;
    }

    private static int[] stringToIntArray(String s) {
        int count = s.length();
        char[] char_1 = s.toCharArray();
        int[] int_1 = new int[count];
        for(int i=0;i<count;i++){
            int_1[i] = char_1[i]-'0';
        }
        return int_1;
    }

    private static void initialNetPlan() {
        String ch = "/Users/shentianyu/Desktop/vnf/networkTopologies/6nodes_16links.n2p";
        File f1 = new File(ch);
        NetPlan netPlan = new NetPlan(f1);
        netPlan.setAttribute("OccupiedSlot","0");
        netPlan.setAttribute("MFSI","0");
        netPlan.setAttribute("TotalUsedCPU","0");
        netPlan.setAttribute("AvgMFSI","0");
        netPlan.setAttribute("NumberOfHops","0");
        netPlan.setAttribute("BlockedRequest","0");
        netPlan.setAttribute("AverageCost","0");
        netPlan.setAttribute("TotalDelayTime","0");
        netPlan.setAttribute("TotalThresholdTime","0");

        int len = numberOfDC;
        int[] nums = {0,1,2,3,4,5};
        Set<Integer> set = new HashSet<>();
        Random random = new Random();
        int i ;
        while(true){
            i = random.nextInt(nums.length);
            set.add(nums[i]);
            if(set.size()>=len){
                break;
            }
        }

        int numberOfNodes = netPlan.getNumberOfNodes();
        for(int j = 0;j<numberOfNodes;j++){
            if(set.contains(j)){
                netPlan.getNode(j).setAttribute("DataCenter","1");
                netPlan.getNode(j).setAttribute("VNF","0");
                for(int vnfType = 1;vnfType<=numberOfAllVNFTypes;vnfType++){
                    netPlan.getNode(j).setAttribute(String.valueOf(vnfType),"0");
                }
            } else {
                netPlan.getNode(j).setAttribute("DataCenter","0");
            }
        }

        netPlan = removeLayers(netPlan);
        netPlan = removeAllLayerDemand(netPlan);
        netPlan = substrateNetPlanAttribute(netPlan);

        File f_1 = new File(ch);
        netPlan.saveToFile(f_1);
    }

    private static NetPlan substrateNetPlanAttribute(NetPlan netPlan) {
        List<Link> links = netPlan.getLinks();
        String capacityOfSlots = setAttributeOfSituationOfSlots();
        for(Link link:links){
            link.setAttribute("LinkStatus",capacityOfSlots);
            link.setCapacity(numberOfALLSlots);
        }
        return netPlan;
    }

    private static String setAttributeOfSituationOfSlots() {
        char[] situationOfSlot = new char[numberOfALLSlots];
        for(int i=0;i<numberOfALLSlots;i++){
            situationOfSlot[i] = '0';
        }
        String situationOfSlots = new String(situationOfSlot);
        return situationOfSlots;
    }

    private static NetPlan removeAllLayerDemand(NetPlan netPlan) {
        for(NetworkLayer networkLayer:netPlan.getNetworkLayers()){
            netPlan.removeAllDemands(networkLayer);
        }
        return netPlan;
    }

    private static NetPlan removeLayers(NetPlan netPlan) {
        List<Long> names = new ArrayList<>();
        int numberOfNetworkLayers = netPlan.getNumberOfLayers();
        for(int i = 1;i<numberOfNetworkLayers;i++){
            Long name = netPlan.getNetworkLayer(i).getId();
            names.add(name);
        }
        for(Long name:names){
            netPlan.removeNetworkLayer(netPlan.getNetworkLayerFromId(name));
            netPlan = netPlan.copy();
        }
        return netPlan;
    }

    public static NetPlan createOneNetPlan(){
        NetPlan netPlan = new NetPlan();
        netPlan = createNode(netPlan);
        netPlan = createLink(netPlan);

        netPlan.setAttribute("DelayTime","0");
        double thresholdTime = 0;
        for(Node node:netPlan.getNodes()){
            int vnfType = Integer.valueOf(node.getAttribute("VNF")).intValue();
            if(vnfType!=0){
                thresholdTime += (vnfType+1)*5*numberOfThresholdVNF;
            }
        }
        thresholdTime += 10;
        netPlan.setAttribute("ThresholdTime",String.valueOf(thresholdTime));
        netPlan.setAttribute("Block","0");
        for(Link link:netPlan.getLinks()){
            link.setAttribute("PathLength","0.0");
        }
        return netPlan;
    }

    private static NetPlan createNode(NetPlan netPlan) {
        Random r = new Random();
        int n = (int)(Math.random()*2)+3;
        double xmax = 100;
        double xmin = 0;
        double ymax = 100;
        double ymin = 0;
        for(int i = 0;i<n;i++){
            double xCoord = xmin+(xmax-xmin)*r.nextDouble();
            double yCoord = ymin+(ymax-ymin)*r.nextDouble();
            Node node = netPlan.addNode(xCoord,yCoord,"Node"+i,null);
        }
        return netPlan;
    }

    private static NetPlan createLink(NetPlan netPlan) {
        int numberOfNodes = netPlan.getNumberOfNodes();
        Node sourceNode = netPlan.getNode(0);
        sourceNode.setAttribute("VNF","0");
        sourceNode.setAttribute("MappedNode","0");
        Node destinationNode = netPlan.getNode(numberOfNodes-1);
        destinationNode.setAttribute("VNF","0");
        destinationNode.setAttribute("MappedNode","0");

        Set<Integer> vnfTypeSet = new HashSet<>();
        vnfTypeSet.add(0);
        for(int i=1;i<numberOfNodes-1;i++){
            Node middleNode = netPlan.getNode(i);
            int vnfType = 0;
            while(true){
                vnfType = 1+(int)(Math.random()*numberOfAllVNFTypes);
                if(!vnfTypeSet.contains(vnfType)){
                    vnfTypeSet.add(vnfType);
                    break;
                }
            }
            middleNode.setAttribute("VNF",String.valueOf(vnfType));
            middleNode.setAttribute("MappedNode","0");
        }

        //[10,100)
        double p = Math.random()*90+10;
        for(int i=0;i<=numberOfNodes-2;i++){
            double dist = netPlan.getNodePairEuclideanDistance(netPlan.getNode(i),netPlan.getNode(i+1));
            netPlan.addLink(netPlan.getNode(i),netPlan.getNode(i+1),p,dist,1,null,netPlan.getNetworkLayerDefault()).setCapacity(p);
        }
        return netPlan;
    }


    static class NodeMappingReturn{

        public boolean nodeMappingSign;

        public boolean isNodeMappingSign(){
            return nodeMappingSign;
        }

        public void setNodeMappingSign(boolean nodeMappingSign) {
            this.nodeMappingSign = nodeMappingSign;
        }
    }

    static class LinkMappingReturn{

        public boolean linkMappingSign;

        public boolean isLinkMappingSign(){
            return linkMappingSign;
        }

        public void setLinkMappingSign(boolean linkMappingSign) {
            this.linkMappingSign = linkMappingSign;
        }
    }

}

